#!/usr/bin/env python
#
# Copyright 2007 Doug Hellmann.
#
"""

"""

__version__ = "$Id$"

# Import system modules
from django.shortcuts import render_to_response

import logging

# Import local modules
from models import *
from docket import utils

# Module

logger = logging.getLogger('docket.views')

def case(request, year, casenum):
    logger.debug('case(%s, %s)', year, casenum)
    the_case = Case.objects.get(year=int(year), num=casenum)
    
    month_list = utils.months_in_year(the_case.year)
    
    # This is stupid, but seems to be the only way to build this
    # order_by() properly.
    participants = the_case.participant_set.all().extra(
                tables=['docket_role'],
                where=["docket_role.id = docket_participant.role_id"],
                )
    participants = participants.order_by(
                'docket_role.display_order', 
                'last_name',
                'first_name')
    mediafiles = the_case.mediafile_set.all()

    return render_to_response('case.html', {'case':the_case,
                                            'defendant':the_case.defendant(),
                                            'month_list':month_list,
                                            'decade':(int(year)/10)*10,
                                            'participants':participants,
                                            'mediafiles':mediafiles,
                                            })
                                            
SEARCH_TERMS_TO_FIELDS = {
    'first_name':'first_name',
    'last_name':'last_name',
}

def search(request):
    # Search parameters are passed via GET
    logger.debug('search %s', str(request.GET))
    logger.debug('type GET: %s', type(request.GET))
    
    # Convert search arguments to query arguments
    filter_args = {}
    search_terms = {}
    search_type = 'exact'
    for name in request.GET:
        value = request.GET[name].strip()
        logger.debug('%s="%s"', name, value)
        if name == 'search_type':
            search_type = value.lower()
            continue
        field = SEARCH_TERMS_TO_FIELDS.get(name)
        if field is not None:
            if value:
                filter_args[field] = value
                search_terms[name] = value
    logger.debug('search_type = %s', search_type)
    logger.debug('filter_args = %s', filter_args)

    # Defaults for template parameters
    filtered_results = None # converted to a list later
    messages = []
    
    if not search_terms:
        # No arguments, do nothing
        pass

    # Set up the QuerySet (cases), count variable (num_cases), and error message (message)        
    elif search_type == 'exact':
        # Find the cases matching the query
        modified_filter_args = {}
        for name, value in filter_args.iteritems():
            modified_filter_args[name + '__iexact'] = value            
        logger.debug('modified_filter_args=%s', modified_filter_args)
        filtered_results = Participant.objects.filter(**modified_filter_args)
        
    elif search_type == 'contains':
        modified_filter_args = {}
        for name, value in filter_args.iteritems():
            modified_filter_args[name + '__icontains'] = value            
        logger.debug('modified_filter_args=%s', modified_filter_args)
        filtered_results = Participant.objects.filter(**modified_filter_args)
        
    elif search_type == 'soundex':
        where_clauses = []
        where_params = []
        for name, value in filter_args.iteritems():
            # ignore short search terms
            if len(value) < 3:
                messages.append('"%s" is too short for soundex searches, ignored' % value)
                continue
            where_clauses.append("%s != ''" % name) # field cannot be empty
            where_clauses.append('soundex(%s) = soundex(%%s)' % name)
            where_params.append(value)

        logger.debug('where_clauses=%s', where_clauses)
        logger.debug('where_params=%s', where_params)

        if where_clauses:
            filtered_results = Participant.objects.all().extra(where=where_clauses, 
                                                               params=where_params)
        
    elif search_type == 'metaphone':
        where_clauses = []
        where_params = []
        for name, value in filter_args.iteritems():
            # ignore short search terms
            if len(value) < 3:
                messages.append('"%s" is too short for metaphone searches, ignored' % value)
                continue
            where_clauses.append("%s != ''" % name) # field cannot be empty
            where_clauses.append('metaphone(%s, 10) = metaphone(%%s, 10)' % name)
            where_params.append(value)

        logger.debug('where_clauses=%s', where_clauses)
        logger.debug('where_params=%s', where_params)

        if where_clauses:
            filtered_results = Participant.objects.all().extra(where=where_clauses, 
                                                               params=where_params)
        
    else:
        raise NotImplementedError('Cannot search by %s yet' % search_type)
    
    results = []
    num_results = 0
    if filtered_results is not None:    
        num_results = filtered_results.count()
        if not num_results:
            results = []
            if not search_terms:
                messages.append('Please enter search terms')
            else:
                messages.append('No matches found')
        else:
            # Add a few extra columns so we can use them to sort.
            results = filtered_results.extra(
                tables=['docket_case'],
                select={'caseyear':'docket_case.year', 
                        # Even though the number almost always holds a sequence of digits,
                        # it sometimes includes non-digit values because we have situations
                        # like case 1906/434b.  Try to convert the field to a number for 
                        # sorting, so the results are displayed in the proper order.
                        'casenum':"to_number(docket_case.num, '9999')",
                        }, 
                where=['docket_case.id = case_id']).order_by('caseyear', 'casenum')

    logger.debug('%d results', num_results)
    logger.debug('search_terms: %s' % str(search_terms))
    logger.debug('messages="%s"', messages)

    render_args = { 'results':results,
                    'num_results':num_results,
                    'messages':messages,
                    'search_terms':search_terms,
                    'search_type':search_type,
                    }
    
    return render_to_response('search_results.html', render_args)
    
